package com.wh1200.mybatis.xmlless

import com.wh1200.mybatis.xmlless.annotations.Count
import com.wh1200.mybatis.xmlless.annotations.JoinTableColumn
import com.wh1200.mybatis.xmlless.annotations.LogicDeleteStatus
import com.wh1200.mybatis.xmlless.annotations.SelectedProperties
import com.wh1200.mybatis.xmlless.constant.Annotations
import com.wh1200.mybatis.xmlless.enums.XmllessFieldFill
import com.wh1200.mybatis.xmlless.enums.XmllessFieldStrategy
import com.wh1200.mybatis.xmlless.model.base.BaseSimpleClassWrapper
import com.wh1200.mybatis.xmlless.model.base.BaseTableFieldWrapper
import com.wh1200.mybatis.xmlless.model.dto.JavaSimpleClassWrapper
import com.wh1200.mybatis.xmlless.model.exception.XmlLessException
import com.wh1200.mybatis.xmlless.util.AnnotationUtil
import com.baomidou.mybatisplus.annotation.FieldFill
import com.baomidou.mybatisplus.annotation.FieldStrategy
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo

/**
 *
 * @author 吴昊
 * @date 2024/1/19 10:40
 * @since v0.0.0
 * @version 1.0
 */
class PlusTableFieldWrapper(private val info: TableFieldInfo) : BaseTableFieldWrapper {

  override fun getFieldName(): String {
    return info.property
  }

  override fun getColumn(): String {
    return info.column
  }

  override fun getInsertStrategy(): XmllessFieldStrategy {
    return toXmllessStrategy(info.insertStrategy!!)
  }

  override fun getUpdateStrategy(): XmllessFieldStrategy {
    return toXmllessStrategy(info.updateStrategy!!)
  }

  override fun getFieldFillStrategy(): XmllessFieldFill {
    return when (info.fieldFill!!) {
      FieldFill.DEFAULT       -> XmllessFieldFill.DEFAULT
      FieldFill.INSERT        -> XmllessFieldFill.INSERT
      FieldFill.UPDATE        -> XmllessFieldFill.UPDATE
      FieldFill.INSERT_UPDATE -> XmllessFieldFill.INSERT_UPDATE
    }
  }

  override fun isCharSequence(): Boolean {
    return info.isCharSequence
  }

  override fun isMarkedCreatedBy(): Boolean {
    return AnnotationUtil.hasAnnotation(info.field, Annotations.CREATED_BY)
  }

  override fun isMarkedDeletedBy(): Boolean {
    return AnnotationUtil.hasAnnotation(info.field, Annotations.DELETED_BY)
  }

  override fun isMarkedDeletedDate(): Boolean {
    return AnnotationUtil.hasAnnotation(info.field, Annotations.DELETED_DATE)
  }

  override fun isMarkedLastModifiedBy(): Boolean {
    return AnnotationUtil.hasAnnotation(info.field, Annotations.LAST_MODIFIED_BY)
  }

  override fun isMarkedCreatedDate(): Boolean {
    return AnnotationUtil.hasAnnotation(info.field, Annotations.CREATED_DATE)
  }

  override fun isMarkedLastModifiedDate(): Boolean {
    return AnnotationUtil.hasAnnotation(info.field, Annotations.LAST_MODIFIED_DATE)
  }

  override fun getCount(): Count? {
    return AnnotationUtil.resolve<Count>(info.field)
  }

  override fun getUpdate(): String? {
    return info.update
  }

  override fun getJoinTableColumn(): JoinTableColumn? {
    return AnnotationUtil.resolve<JoinTableColumn>(info.field)
  }

  override fun getSelectedProperties(): List<String> {
    return info.field.getAnnotation(SelectedProperties::class.java)?.value?.toList() ?: listOf()
  }

  override fun isLogicDelete(): Boolean {
    if (info.field.isAnnotationPresent(LogicDeleteStatus::class.java)) {
      if (info.isLogicDelete) {
        throw XmlLessException("字段${info.field.declaringClass.name}.${this.getFieldName()}不能同时标记@LogicDeleteStatus和@TableLogic")
      }
      return true
    }
    return info.isLogicDelete
  }

  override fun getLogicDelValueInner(): String? {
    return if (info.field.isAnnotationPresent(LogicDeleteStatus::class.java)) {
      info.field.getAnnotation(LogicDeleteStatus::class.java).deletedValue
    } else {
      info.logicDeleteValue
    }
  }

  override fun getLogicNotDelValueInner(): String? {
    return if (info.field.isAnnotationPresent(LogicDeleteStatus::class.java)) {
      info.field.getAnnotation(LogicDeleteStatus::class.java).notDeleteValue
    } else {
      info.logicNotDeleteValue
    }
  }

  override fun getFieldType(): BaseSimpleClassWrapper {
    return JavaSimpleClassWrapper(info.propertyType)
  }

  private fun toXmllessStrategy(plusFieldStrategy: FieldStrategy): XmllessFieldStrategy {
    return when (plusFieldStrategy) {
      FieldStrategy.IGNORED   -> XmllessFieldStrategy.NEVER
      FieldStrategy.ALWAYS    -> XmllessFieldStrategy.ALWAYS
      FieldStrategy.NOT_NULL  -> XmllessFieldStrategy.NOT_NULL
      FieldStrategy.NOT_EMPTY -> XmllessFieldStrategy.NOT_EMPTY
      FieldStrategy.DEFAULT   -> XmllessFieldStrategy.DEFAULT
      FieldStrategy.NEVER     -> XmllessFieldStrategy.NEVER
    }
  }

}
